package com.kaithan.framework.common.util;

import com.google.common.collect.Lists;
import com.kaithan.framework.common.encode.Encodes;
import org.apache.commons.text.StringEscapeUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.springframework.util.StringUtils.trimWhitespace;

/**
 * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
 *
 * @author ThinkGem
 * @version 2013-05-22
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {

    private static final char SEPARATOR = '_';
    private static final String CHARSET_NAME = "UTF-8";

    public static boolean isEmpty(Object o) {
        if (o instanceof String) {
            return isEmpty((String) o);
        }
        return o == null;
    }

    public static boolean isNotEmpty(Object o) {
        if (o instanceof String) {
            return isNotEmpty((String) o);
        }
        return o != null;
    }

    public static boolean hasText(String str) {
        return isNotBlank(str);
    }

    /**
     * 转换为字节数组
     *
     * @param str
     * @return
     */
    public static byte[] getBytes(String str) {
        if (str != null) {
            try {
                return str.getBytes(CHARSET_NAME);
            } catch (UnsupportedEncodingException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 转换为字节数组
     *
     * @param bytes
     * @return
     */
    public static String toString(byte[] bytes) {
        try {
            return new String(bytes, CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inString(String str, String... strs) {
        if (str != null) {
            for (String s : strs) {
                if (str.equals(trimWhitespace(s))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 替换掉HTML标签方法
     */
    public static String replaceHtml(String html) {
        if (isEmpty(html)) {
            return "";
        }
        String regEx = "<.+?>";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(html);
        String s = m.replaceAll("");
        return s;
    }

    /**
     * 替换为手机识别的HTML，去掉样式及属性，保留回车。
     *
     * @param html
     * @return
     */
    public static String replaceMobileHtml(String html) {
        if (html == null) {
            return "";
        }
        return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
    }

    /**
     * 替换为手机识别的HTML，去掉样式及属性，保留回车。
     *
     * @param txt
     * @return
     */
    public static String toHtml(String txt) {
        if (txt == null) {
            return "";
        }
        return replace(replace(Encodes.escapeHtml(txt), "\n", "<br/>"), "\t", "&nbsp; &nbsp; ");
    }

    /**
     * 缩略字符串（不区分中英文字符）
     *
     * @param str    目标字符串
     * @param length 截取长度
     * @return
     */
    public static String abbr(String str, int length) {
        if (str == null) {
            return "";
        }
        try {
            StringBuilder sb = new StringBuilder();
            int currentLength = 0;
            for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
                currentLength += String.valueOf(c).getBytes("GBK").length;
                if (currentLength <= length - 3) {
                    sb.append(c);
                } else {
                    sb.append("...");
                    break;
                }
            }
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String abbr2(String param, int length) {
        if (param == null) {
            return "";
        }
        StringBuffer result = new StringBuffer();
        int n = 0;
        char temp;
        boolean isCode = false; // 是不是HTML代码
        boolean isHTML = false; // 是不是HTML特殊字符,如&nbsp;
        for (int i = 0; i < param.length(); i++) {
            temp = param.charAt(i);
            if (temp == '<') {
                isCode = true;
            } else if (temp == '&') {
                isHTML = true;
            } else if (temp == '>' && isCode) {
                n = n - 1;
                isCode = false;
            } else if (temp == ';' && isHTML) {
                isHTML = false;
            }
            try {
                if (!isCode && !isHTML) {
                    n += String.valueOf(temp).getBytes("GBK").length;
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            if (n <= length - 3) {
                result.append(temp);
            } else {
                result.append("...");
                break;
            }
        }
        // 取出截取字符串中的HTML标记
        String temp_result = result.toString().replaceAll("(>)[^<>]*(<?)",
                "$1$2");
        // 去掉不需要结素标记的HTML标记
        temp_result = temp_result
                .replaceAll(
                        "</?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>",
                        "");
        // 去掉成对的HTML标记
        temp_result = temp_result.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)</\\1>",
                "$2");
        // 用正则表达式取出标记
        Pattern pattern = Pattern.compile("<([a-zA-Z]+)[^<>]*>");
        Matcher m = pattern.matcher(temp_result);
        List<String> endHTML = Lists.newArrayList();
        while (m.find()) {
            endHTML.add(m.group(1));
        }
        // 补全不成对的HTML标记
        for (int i = endHTML.size() - 1; i >= 0; i--) {
            result.append("</");
            result.append(endHTML.get(i));
            result.append(">");
        }
        return result.toString();
    }

    /**
     * 转换为Double类型
     */
    public static Double toDouble(Object val) {
        if (val == null) {
            return 0D;
        }
        try {
            return Double.valueOf(trimWhitespace(val.toString()));
        } catch (Exception e) {
            return 0D;
        }
    }

    /**
     * 转换为Float类型
     */
    public static Float toFloat(Object val) {
        return toDouble(val).floatValue();
    }

    /**
     * 转换为Long类型
     */
    public static Long toLong(Object val) {
        return toDouble(val).longValue();
    }

    /**
     * 转换为Integer类型
     */
    public static Integer toInteger(Object val) {
        return toLong(val).intValue();
    }

    // /**
    //  * 获得i18n字符串
    //  */
    // public static String getMessage(String code, Object[] args) {
    //     LocaleResolver localLocaleResolver = SpringContextUtil.getBean(LocaleResolver.class);
    //     HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    //     Locale localLocale = localLocaleResolver.resolveLocale(request);
    //     return SpringContextUtil.getApplicationContext().getMessage(code, args, localLocale);
    // }

    /**
     * 获得用户远程地址
     */
    public static String getRemoteAddr(HttpServletRequest request) {
        String remoteAddr = request.getHeader("X-Real-IP");
        if (isEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("X-Forwarded-For");
        } else if (isEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("Proxy-Client-IP");
        } else if (isEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     * toCapitalizeCamelCase("hello_world") == "HelloWorld"
     * toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }

        s = s.toLowerCase();

        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     * toCapitalizeCamelCase("hello_world") == "HelloWorld"
     * toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toCapitalizeCamelCase(String s) {
        if (s == null) {
            return null;
        }
        s = toCamelCase(s);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     * toCapitalizeCamelCase("hello_world") == "HelloWorld"
     * toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toUnderScoreCase(String s) {
        if (s == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            boolean nextUpperCase = true;

            if (i < (s.length() - 1)) {
                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
            }

            if ((i > 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(SEPARATOR);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }

            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

    /**
     * 转换为JS获取对象值，生成三目运算返回结果
     *
     * @param objectString 对象串
     *                     例如：row.user.id
     *                     返回：!row?'':!row.user?'':!row.user.id?'':row.user.id
     */
    public static String jsGetVal(String objectString) {
        StringBuilder result = new StringBuilder();
        StringBuilder val = new StringBuilder();
        String[] vals = split(objectString, ".");
        for (int i = 0; i < vals.length; i++) {
            val.append("." + vals[i]);
            result.append("!" + (val.substring(1)) + "?'':");
        }
        result.append(val.substring(1));
        return result.toString();
    }


    /**
     * 通过设置的数字区间，产生一个区间的随机数.
     *
     * @param a
     * @param b
     * @return 随机值 ，不会返回最大的值。
     */
    public static Integer getRandomByQJ(int a, int b) {
        int s = 0;
        if (a == b) {
            s = a;
        } else {
            int min = a > b ? b : a;//求得最小值
            int fw = Math.abs(a - b);//求得两值差
            int sj = (int) (Math.random() * fw);//产生随机数
            s = min + sj;
        }
        return s;
    }

    /**
     * 文件中文下载时候使用的转码类
     *
     * @param isMSIE
     * @param s
     * @return
     */
    public static String toUtf8String(boolean isMSIE, String s) {
        if (isMSIE) {
            try {
                s = java.net.URLEncoder.encode(s, "UTF8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else {
            try {
                s = new String(s.getBytes("UTF-8"), "ISO-8859-1");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return s;
    }

    /**
     * 把中文转成Unicode码
     *
     * @param str
     * @return
     */
    public static String chinaToUnicode(String str) {
        String result = "";
        for (int i = 0; i < str.length(); i++) {
            int chr1 = (char) str.charAt(i);
            if (chr1 >= 19968 && chr1 <= 171941) {//汉字范围 \u4e00-\u9fa5 (中文)
                result += "\\u" + Integer.toHexString(chr1);
            } else {
                result += str.charAt(i);
            }
        }
        return result;
    }

    /**
     * Unicode转换成 中文
     *
     * @param unicodeStr
     * @return
     */
    public static String unicodeToString(String unicodeStr) {
        //待开发
        return null;
    }

    /**
     * 判断是否为中文字符
     *
     * @param c
     * @return
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    /**
     * java去除字符串中的空格、回车、换行符、制表符
     *
     * @return
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = pattern.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
		/*	    笨方法：String s = "你要去除的字符串";
		        1.去除空格：s = s.replace('\\s','');
		        2.去除回车：s = s.replace('\n','');
		注：\n 回车(\u000a) 
		 \t 水平制表符(\u0009) 
		 \s 空格(\u0008) 
		 \r 换行(\u000d) */

    }

    /**
     * List<String>转换成 xx1,xx2  字符串
     *
     * @param list
     * @return
     */
    public static String toStringBySpilt(List<String> list) {
        if (list != null && list.size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0, b = list.size(); i < b; i++) {
                String s = list.get(i);
                if (StringUtils.isNotBlank(s)) {
                    if (i < b - 1) {
                        sb.append(s).append(",");
                    } else {
                        sb.append(s);
                    }
                }
            }
            return sb.toString();
        } else {
            return "";
        }
    }

    /**
     * List<String>转换成 'xx1','xx2'  字符串
     *
     * @param list
     * @return
     */
    public static String toStringBySqlIn(List<String> list) {
        if (list != null && list.size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0, b = list.size(); i < b; i++) {
                String s = list.get(i);
                if (StringUtils.isNotBlank(s)) {
                    if (i < b - 1) {
                        sb.append("'").append(s).append("',");
                    } else {
                        sb.append("'").append(s).append("'");
                    }
                }
            }
            return sb.toString();
        } else {
            return "'-0'";
        }
    }

    /**
     * Object[] 转换成 'xx1','xx2'  字符串
     *
     * @return
     */
    public static String toStringBySqlIn(String[] ss) {
        if (ss != null && ss.length > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0, b = ss.length; i < b; i++) {
                String s = ss[i];
                if (StringUtils.isNotBlank(s)) {
                    if (i < b - 1) {
                        sb.append("'").append(s).append("',");
                    } else {
                        sb.append("'").append(s).append("'");
                    }
                }
            }
            return sb.toString();
        } else {
            return "";
        }
    }

    /**
     * 根据传入的String数组，清除空值，包括""。
     *
     * @param objs
     * @return Object[]数组
     */
    public static String[] getArrayByArray(String[] objs) {
        if (objs != null && objs.length > 0) {
            List<String> list = new ArrayList<>();
            for (String o : objs) {
                if (isNotBlank(o)) {
                    list.add(o);
                }
            }
            String[] ss = new String[list.size()];
            for (int i = 0, b = list.size(); i < b; i++) {
                ss[i] = list.get(i);
            }
            return ss;
        } else {
            return new String[]{};
        }
    }

    /**
     * 获取32位UUID
     *
     * @return
     */
    public static String getUUID32() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 获取36位UUID
     *
     * @return
     */
    public static String getUUID36() {
        return UUID.randomUUID().toString();
    }

    public static boolean isNumber(String s) {
        if (s.length() == 0) {
            return false;
        }
        for (char c : s.toCharArray()) {
            if (!Character.isDigit(c)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 功能描述: solr查询条件中，如果有[+\-&|!(){}\[\]^"~*?:(\)]字符，需要进行转义
     *
     * @param input
     * @return : java.lang.String
     * @author : 陈沐荣
     * @since : 2020/10/10
     */
    public static String transformSolrMetacharactor(String input) {
        StringBuffer sb = new StringBuffer();
        String regex = "[+\\-&|!(){}\\[\\]^\":~?(\\)]";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            matcher.appendReplacement(sb, "\\\\" + matcher.group());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 方法说明：给定一个字符串，如果字符串不为空，则返回它本身，否则返回默认值
     *
     * @param s            字符串
     * @param defaultValue 默认值
     * @return {@link String }
     */
    public static String getStr(String s, String defaultValue) {
        if (StringUtils.isBlank(s)) {
            return defaultValue;
        }
        return s;
    }

    /**
     * 方法说明：判断给定字符串中是否包含中文
     *
     * @param str str
     * @return boolean
     */
    public static boolean isContainChinese(String str) {
        Pattern pattern = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = pattern.matcher(str);
        return m.find();
    }

    /**
     * 方法说明：从给定的字符串中提取中文汉字
     *
     * @param str str
     * @return {@link String }
     */
    public static String getChineseWords(String str) {
        char[] chars = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (char aChar : chars) {
            if (aChar > 127 || aChar < 0) {
                stringBuilder.append(aChar);
            }
        }
        return stringBuilder.toString();
    }

    /**
     * 将字符串的首字母转大写
     * @param s 给定的字符串
     * @return 返回首字母大写的字符串
     */
    public static String toUpperFirstCharacter(String s) {
        // 利用ascii编码的前移，效率要高于截取字符串进行转换的操作
        char[] cs = s.toCharArray();
        if (Character.isLowerCase(cs[0])) {
            cs[0] -= 32;
            return String.valueOf(cs);
        }
        return s;
    }

    /**
     * 方法说明：判断字符串是否是uuid
     *
     * @param s 给定字符串
     * @return boolean
     * @author 祝印
     * @since 2023年03月29日 16:11:19
     */
    public static boolean isUUID(String s){
        if (StringUtils.isBlank(s)) {
            return false;
        }
        return s.matches("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") || s.matches("^[0-9a-fA-F]{8}[0-9a-fA-F]{4}[0-9a-fA-F]{4}[0-9a-fA-F]{4}[0-9a-fA-F]{12}$");
    }

    /***
     * 驼峰命名转为下划线命名
     * "clientNo" 转为下划线命名：client_no
     * @param humpStr 驼峰命名的字符串
     * @return 返回下划线形式的字符串
     */
    public static String humpToUnderline(String humpStr) {
        if (isBlank(humpStr) || isAllUpperCase(humpStr) || isAllLowerCase(humpStr)) {
            // 空串或者全大写或者全小写的直接返回
            return humpStr;
        }

        StringBuilder sb = new StringBuilder(humpStr);
        int temp = 0;
        String underLineFlag = "_";
        if (!humpStr.contains(underLineFlag)) {
            for (int i = 0; i < humpStr.length(); i++) {
                if (Character.isUpperCase(humpStr.charAt(i))) {
                    sb.insert(i + temp, "_");
                    temp += 1;
                }
            }
        }
        return sb.toString().toLowerCase();
    }

    public static boolean isBlank(String... strs) {
        for (int i = 0; i < strs.length; i++) {
            if (isBlank(strs[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成指定长度的加密盐
     * @param byteLength 盐的字节长度
     * @return 加密盐
     */
    public static String generateSalt(int byteLength) {
        SecureRandom random = new SecureRandom();
        byte[] saltBytes = new byte[byteLength];
        random.nextBytes(saltBytes);
        // 将字节数组转换为十六进制字符串表示
        StringBuilder hexString = new StringBuilder();
        for (byte b : saltBytes) {
            String hex = Integer.toHexString(0xff & b);
            if(hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
    
}
